export default class Tree<T = any> {
    childrens?: Tree<T>[]
    parent?: Tree<T>
    val: T
    constructor(val: T, parent?: Tree<T>, childrens?: Tree<T>[]) {
        this.val = val
        this.parent = parent
        this.childrens = childrens
    }
    getBrothers(): Tree<T>[] {
        if (this.parent) {
            return this.parent.childrens || []
        }
        return []
    }
    accessPosterity(fun: (input: Tree<T>, index: number) => boolean | void, index?: number) {
        let desIndex = index || -1
        if (desIndex == -1 && this.parent) {
            desIndex = this.parent.childrens!.findIndex((v) => v == this)
        }
        if (fun(this, desIndex) === false) {
            return
        }
        if (this.childrens) {
            this.childrens.forEach((v, index) => v.accessPosterity(fun, index))
        }
    }
    accessBrothers(fun: (input: Tree<T>[]) => void) {
        let brothers = this.getBrothers()
        if (brothers.length > 0) {
            fun(brothers)
            if (this.parent) {
                this.parent.accessBrothers(fun)
            }
        }
    }
    getAllLeaf(): Tree<T>[] {
        const res: Tree<T>[] = []
        this.accessPosterity((input: Tree<T>) => {
            if (!input.childrens || input.childrens.length == 0) {
                res.push(input)
            }
        })
        return res
    }
    deleteNode(val?: Tree<T>) {
        if (!val) {
            return
        }
        this.accessPosterity((input: Tree<T>, index: number) => {
            if (val == input) {
                if (!input.parent) {
                    input.childrens?.splice(0, input.childrens.length)
                    return false
                }
                if (input.getBrothers().length == 1) {
                    input.parent!.deleteNode(input.parent!)
                    return false
                }
                if (index > -1) {
                    input.parent!.childrens!.splice(index, 1)
                }
            }
        })
    }
}
